package org.moyrax.nereyda.lib
{
	/**
	 * Esta colección permite tener asociados varios valores
	 * a una misma clave. Se basa en <b>HashCollection</b>
	 * por lo que podrá utilizarse de ambas maneras, con la
	 * diferencia que no se verificará la existencia de una
	 * clave única, a menos que se especifique en la propiedad
	 * <i>strict</i>
	 */
	public class MultiMapCollection extends HashCollection
	{
		/**
		 * Indica si el comportamiento será el predeterminado,
		 * o si el objeto se utilizará como un HashCollection común.
		 * Este valor será de sólo lectura una vez que la colección
		 * ya ha sido inicializada con elementos.
		 */
		[Bindable]
		private var _strict :Boolean = false;
		
		public function get strict():Boolean
		{
			return( this._strict );
		}
		
		public function set strict( value:Boolean ):void
		{
			if ( this.length > 0 )
			{
				return;
			}
			
			this._strict = value;
		}
		
		public function MultiMapCollection( source:Array = null )
		{
			super( source );
		}

		/**
		 * Agrega un nuevo elemento a la colección.
		 * 
		 * @param key   Clave a la que corresponde el elemento.
		 * @param value Elemento que se agregará.
		 */
		override public function put( key:Object, value:Object ):void 
		{
			if ( this.strict ) {
				super.put( key, value );
			}
			else {
				var keyMapIndex :int = this.keyMap.indexOf( key );
	
				super.addItem( value );
	
				this.keyMap.push( key );
				this.tableMap.push( value );
			}
		}

		/**
		 * Devuelve un array con todos los elementos que 
		 * corresponden a la clave especificada.
		 * 
		 * @param key   Clave de referencia.
		 */
		override public function get( key:Object ):Object 
		{
			var keyMap :Array = super.keyMap;
			
			var mapList :Array = super.tableMap.filter(
				function( item:Object, index:int, array:Array ):Boolean
				{
					if ( keyMap[index] === key )
					{
						return( true );
					}
					
					return( false );
				}
			);

			return( mapList );
		}
		
		/**
		 * Elimina todos los elementos de la clave especificada.
		 * 
		 * @param key Clave de referencia.
		 */
		override public function remove( key:Object ):Object 
		{
			var keyMap :Array = super.keyMap;
			
			var removeList :Array = this.get( key ) as Array;
			
			for( var i:int = 0; i < removeList.length; i++ )
			{
				super.remove( key );
			}

			return( removeList );
		}
	}
}